package de.herberlin.showheader;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.event.*;

/**
 * Action Handling class extends form editor generated user interface.
 * 
 * @author Hans Joachim Herbertz
 */
public class Main
	extends Gui11
	implements ProgressListener, ActionListener, ChangeListener,HyperlinkListener {

	public static final String VERSION="ShowHeader v. 2.0 dev";
	public static final String CRLF="\n";
	public static final String HELP_START_PAGE="rfc2616.html";
	public static final String HELP_PATH="/rfc/";

	/**
	 * Flag is set if something changed in the first panel and a 
	 * reload should happen when switching to the second panel.
	 */
	private boolean triggerReload = true;

	/**
	 * Call the ui - class constructor. 
	 */
	public Main() {
		super();
		setSize(320,240);
		setTitle(VERSION);
		show();
		makeListeners();
		outputArea.setLineWrap(false);
		helpArea.setEditable(false);
		helpArea.setContentType("text/html");
		helpArea.addHyperlinkListener(this);
		try {
			helpArea.setPage(getClass().getResource(HELP_PATH+HELP_START_PAGE));
		} catch (Throwable t){
			t.printStackTrace();	
		}
	}

	public void hyperlinkUpdate(HyperlinkEvent e){
		System.out.println(e.getURL());
		if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)){
			URL url=e.getURL();
			try {
				helpArea.setPage(url);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	private void makeListeners() {
		btnHttp10.setSelected(true);
		progressBar.setMaximum(ProgressEvent.MAX);
		progressBar.setMinimum(ProgressEvent.MIN);
		

		urlCombo.addActionListener(this);
		btnTrace.addActionListener(this);
		btnHttp11.addActionListener(this);
		btnHttp10.addActionListener(this);
		tabbedPane.addChangeListener(this);
		
		requestTextArea.addCaretListener(new CaretListener() {
			public void caretUpdate(CaretEvent e){
				triggerReload=true;
			};
		});
	}

	/**
	 * @see showheader.ProgressListener#progress(showheader.ProgressEvent)
	 */
	public void progress(ProgressEvent action) {
		progressBar.setValue(action.getProgress());
		
		if (action.getError()!=null) {
			progressBar.setValue(ProgressEvent.MAX);
			showError(action.getError());
			
		} else 	if (action.getProgress()==ProgressEvent.MAX) {
			outputArea.setText(new String(((NetworkRequest)action.getSender()).getResposne()));
		}
	}

	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			UIManager.setLookAndFeel("com.incors.plaf.kunststoff.KunststoffLookAndFeel");
		} catch (Throwable  e) {
			e.printStackTrace();
		}
		new Main();
	}

	/**
	 * Action Performed is only used by the first page to update
	 * the headers text area.
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		if (e.getSource().equals(urlCombo) && "comboBoxChanged".equals(e.getActionCommand())) return;
		try {
			URL url=getAddress();
			String headers=null;			
			
			if (btnHttp10.isSelected()) {
				headers="GET "+url.getPath() + " http/1.0"+CRLF
				+CRLF;
			} else if (btnHttp11.isSelected()) {
				headers="GET "+url.getPath() + " http/1.1"+CRLF
				+"Host: "+url.getHost()+CRLF
				+"Connection: close"+CRLF
				+CRLF;
				
			} else /*TRACE*/{
				headers="TRACE "+url.getPath() + " http/1.0"+CRLF
				+"Host: "+url.getHost()+CRLF
				+CRLF;
			}
			requestTextArea.setText(headers);
			triggerReload = true;
		} catch (Exception ex) {
			showError(ex);
		}

	}

	/** Changing the gui to Middle Tab will start the 
	 * Worker thread to send request.
	 * 
	 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
	 */
	public void stateChanged(ChangeEvent e) {
		int actionIndex = 1;
		if (tabbedPane.getSelectedIndex() == actionIndex && triggerReload) {
			try {
				
				URL url=getAddress();
				String headers = getRequestHeaders();

				NetworkRequest req=new NetworkRequest(url);
				progressBar.setValue(ProgressEvent.MIN);	
				outputArea.setText("");			
				req.setListener(this);
				req.sendRequest(headers);
				triggerReload = false;

			} catch (Exception ex) {
				showError(ex);
				tabbedPane.setSelectedIndex(0);
			}
		}
	}
	private void showError(Throwable t) {
		t.printStackTrace();
		JOptionPane.showMessageDialog(
			this,
			t.getMessage(),
			t.getClass().getName(),
			JOptionPane.ERROR_MESSAGE);
	}

	private String getRequestHeaders() throws Exception {
		String ret = requestTextArea.getText();
		if (ret.length() < 5)
			throw new Exception("Request headers too short!");
		if (!ret.endsWith(CRLF+CRLF)) {
			throw new Exception("Headers should end with 2x CRLF");
		}
		return ret;
	}

	/**
	 * Parses url form combo input. Defaults port to 80 and 
	 * protocol to http if not set.
	 * 
	 * @return the parsed url
	 * @throws Exception
	 */
	private URL getAddress() throws Exception {		Object obj=urlCombo.getSelectedItem();
		if (obj==null)throw new Exception("Please enter url.");

		String address = obj.toString();
		if (address.length() < 3) throw new Exception("Please enter valid url.");
		if (!address.startsWith("http://")) {
			address="http://"+address;
		}
		URL url=new URL(address);
		if (url.getPort()==-1) {
			url=new URL("http",url.getHost(),80,url.getPath());
		}
		if ("".equals(url.getPath())){
			url=new URL("http",url.getHost(),80,"/");
		}
		urlCombo.removeItem(url);
		urlCombo.addItem(url);
		urlCombo.setSelectedItem(url);
		return url;

	}

}
